/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ejb;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.*;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author allam
 */
@Stateless
public class NotiziaFacade extends AbstractFacade<Notizia> implements NotiziaFacadeLocal {

    @EJB
    private PiattaformaFacadeLocal piattaformaFacade;
    @EJB
    private UtenteFacadeLocal utenteFacade;
    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    @PersistenceContext(unitName = "EnterpriseApplication12-13-ejbPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public NotiziaFacade() {
        super(Notizia.class);
    }

    /**
     * Cerca l'oggetto sul Database
     *
     * @param n notizia da cercare
     * @return true se notizia e' presente sul Database, false altrimenti
     */
    @Override
    public boolean NotiziaEsistente(Notizia n) {
        String strSQL = "select object(o) from Notizia as o where UPPER(o.titolo) ='" + n.getTitolo().toUpperCase() + "'";

        DateFormat data = new SimpleDateFormat("yyyy-MM-dd");
        String miaData = data.format(n.getData());

        strSQL += " AND UPPER(o.data) ='" + miaData + "'";
        return !(em.createQuery(strSQL).getResultList().isEmpty());
    }

    /**
     * Effettua la cerca di una notizia
     *
     * @param titolo String che rappresenta il titolo della notizia
     * @param data Date che rappresenta la data d'inserimento della notizia
     * @return Notizia se viene trovata, null altrimenti
     */
    public Notizia esiste(String titolo, Date dt) {
        String strSQL = "select object(o) from Notizia as o where UPPER(o.titolo) ='" + titolo.toUpperCase() + "'";
        DateFormat data = new SimpleDateFormat("yyyy-MM-dd");
        String miaData = data.format(dt);
        strSQL += " AND UPPER(o.data) ='" + miaData + "'";

        List l = em.createQuery(strSQL).getResultList();
        if (l.isEmpty()) {
            return null;
        } else {
            return (Notizia) l.get(0);
        }
    }

    /**
     * Trova tutte le notizie presente nel Database
     *
     * @param titolo sottostringa da cercare tra tutti i titoli delle notizie
     * presenti nel Database
     * @param testo sottostringa da cercare nei testi delle notizie presenti nel
     * Database
     * @param piattaforma sottostringa da cercare tra tutte le piattaforme delle
     * notizie presente nel Database
     * @param data data della pubblicazione delle notizie da cercare
     * @return Elenco di notizie, altrimenti restituisce una lista vuota
     */
    @Override
    public List<Notizia> findSome(String titolo, String testo, String piattaforma, String data) throws FileNotFoundException, IOException {
        List<Notizia> ris1=new ArrayList<Notizia>();
        if (titolo != null) {
            String strSQL1 = "select object(o) from Notizia as o where UPPER(o.titolo) LIKE '%" + titolo.toUpperCase() + "%'";
            strSQL1 += " AND UPPER(o.data) LIKE '%" + data.toUpperCase() + "%'";
            ris1 = em.createQuery(strSQL1).getResultList();
        }
        List<Notizia> ris2 = new ArrayList<Notizia>();
        if (piattaforma != null) {
            ///////////////////////////////////////////////////////////////// 
            String strSQL2 = "SELECT n.ID, n.DATA, n.IMMAGINEPATH, n.TESTO, n.TITOLO, n.AUTORE_ID "
                    + "FROM NOTIZIA n, NOTIZIA_PIATTAFORMA np, PIATTAFORMA p "
                    + "WHERE  np.Notizia_ID = n.ID AND p.ID = np.listPiattaforme_ID order by n.data";
            //String strSQL = "select n from Notizia n LEFT JOIN FETCH n.listPiattaforme";//funziona ma per restistuire tutti non si puo usare alias nella tabella NOTIZIA_PIATTAFORMA
            Piattaforma p = piattaformaFacade.esiste(piattaforma);
            long idP;
            if (p != null) {
                idP = p.getId();
                strSQL2 += " AND p.ID =" + idP;//oppure usare np.listPiattaforme_ID
            }
            List l2 = em.createNativeQuery(strSQL2).getResultList();//al posto di createQuery per l'uso di SQL puro standard
             ris2 = new LinkedList();
            Iterator itr = l2.iterator();
            while (itr.hasNext()) {
                Object[] result = (Object[]) itr.next();
                Notizia n = new Notizia();
                n.setId((Long) result[0]);
                n.setData((Date) result[1]);
                n.setImmaginePath((String) result[2]);
                n.setTesto((String) result[3]);
                n.setTitolo((String) result[4]);
                n.setAutore(utenteFacade.find(result[5]));
                ris2.add(n);
            }
        }
        ArrayList<Notizia> risposta = new ArrayList<Notizia>();
        if (testo != null) {
            //////////////////////////////////////////////////////////////////////////////
            ArrayList<String> ric = new ArrayList<String>(Arrays.asList(testo.split(" ")));
            //risposta = new ArrayList<Notizia>();
            for(int i=0;i<ric.size();i++){
           if(ric.get(i).length()<4){
              ric.remove(i);
              i--;
           }
       
       }
        
        /*for (String r : ric) {
            if (r.length() < 4) {
                ric.remove(r);
            }
        }*/
        if (ric.isEmpty())throw new IOException("Errore!! la stringa dovrebbe essere lunga almeno 4 caratteri ");
            List<Notizia> notizia;
            String uri;
            FileInputStream fstream;
            DataInputStream in;
            BufferedReader br;
            String strLine;
            testo = testo.toLowerCase();
            ArrayList<String> aus;
            String sql = "select n from Notizia n order by n.data";
            Query q = em.createQuery(sql);
            notizia = q.getResultList();
            int i;
            for (Notizia not : notizia) {
                uri = not.getTesto();
                fstream = new FileInputStream(uri);
                in = new DataInputStream(fstream);
                br = new BufferedReader(new InputStreamReader(in));

                aus = (ArrayList<String>) ric.clone();
                while (((strLine = br.readLine()) != null) && (!aus.isEmpty())) {
                    i = 0;
                    while (i < aus.size() && (!aus.isEmpty())) {
                        //if (strLine.toLowerCase().contains(aus.get(i))){
                        if (like(strLine, ("%" + aus.get(i).toUpperCase() + "%")) || like(not.getTitolo(), ("%" + aus.get(i).toUpperCase() + "%"))) {

                            aus.remove(aus.get(i));
                        } else {
                            i++;
                        }
                    }
                }
                if (aus.isEmpty()) {
                    risposta.add(not);
                }

                br.close();
                in.close();
                fstream.close();
            }
        }//////////////////////////////////////////////////////////////////////////////
        Set ris = new HashSet();
        ris.addAll(ris2);
        ris.addAll(risposta);
        ris.addAll(ris);
        risposta.clear();
        risposta.addAll(ris);
        return risposta;


    }

    /**
     * ****** Metodo ausiliario like che ha lo stesso funzionamento
     * dell'operatore LIKE di SQL **********
     */
    public static boolean like(String toBeCompare, String by) {
        if (by != null) {
            if (toBeCompare != null) {
                if (by.startsWith("%") && by.endsWith("%")) {
                    int index = toBeCompare.toLowerCase().indexOf(by.replace("%", "").toLowerCase());
                    if (index < 0) {
                        return false;
                    } else {
                        return true;
                    }
                } else if (by.startsWith("%")) {
                    return toBeCompare.endsWith(by.replace("%", ""));
                } else if (by.endsWith("%")) {
                    return toBeCompare.startsWith(by.replace("%", ""));
                } else {
                    return toBeCompare.equals(by.replace("%", ""));
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
     /**
     * Trova tutte le notizie presente nel Database che hanno nella loro lista di piattaforme un nome
     * che matcha con il parametro piattaforma nel Database
     * @param piattaforma sottostringa da cercare tra tutte le piattaforme delle
     * notizie presente nel Database
     * @return Elenco di notizie, altrimenti restituisce una lista vuota
     */

    public List<Notizia> findPlatform(String piattaforma) {
        List<Notizia> ris = null;
        //String strSQL ="select object(o) from Piattaforma as o where UPPER(o.nome) =\'\'" + piattaforma.toUpperCase() + "\'\'";   
        List l = new LinkedList() /*em.createQuery(strSQL).getResultList()*/;
        Piattaforma p = piattaformaFacade.esiste(piattaforma);
        /*if (l.isEmpty())
         p=null;
         else{
         p=(Piattaforma)l.get(0);
         }*/
        ///////////////////////////////////////////////////////////////// 
        String strSQL2 = "SELECT n.ID, n.DATA, n.IMMAGINEPATH, n.TESTO, n.TITOLO, n.AUTORE_ID "
                + "FROM NOTIZIA n, NOTIZIA_PIATTAFORMA np, PIATTAFORMA p "
                + "WHERE  np.Notizia_ID = n.ID AND p.ID = np.listPiattaforme_ID order by n.data";
        // String strSQL = "select n from Notizia n LEFT JOIN FETCH n.listPiattaforme";funziona ma per restistuire tutti non si puo usare alias nella tabella NOTIZIA_PIATTAFORMA

        long idP;
        if (p != null) {
            idP = p.getId();
            strSQL2 += " AND p.ID =" + idP;//oppure usare np.listPiattaforme_ID

            List l2 = em.createNativeQuery(strSQL2).getResultList();//al posto di createQuery per l'uso di SQL puro standard
            List l3 = null;
            ris = new LinkedList<Notizia>();
            Iterator itr = l2.iterator();
            Iterator itr2 = null;
            List<Piattaforma> pl = null;
            Notizia n = null;
            // pl.add(p);
            Object[] result2 = null;
            while (itr.hasNext()) {
                pl = new LinkedList<Piattaforma>();
                Object[] result = (Object[]) itr.next();

                n = new Notizia();
                n.setId((Long) result[0]);
                n.setData((Date) result[1]);
                n.setImmaginePath((String) result[2]);
                n.setTesto((String) result[3]);
                n.setTitolo((String) result[4]);
                n.setAutore(utenteFacade.find(result[5]));

                /*              strSQL2 = "SELECT object(o) "
                 + "FROM NOTIZIA_PIATTAFORMA np, Piattaforma as o "
                 + "WHERE  np.Notizia_ID ="+n.getId()+" AND o.ID = np.listPiattaforme_ID";*/
                strSQL2 = "SELECT p.ID,p.NOME "
                        + "FROM NOTIZIA_PIATTAFORMA np, Piattaforma p "
                        + "WHERE  np.NOTIZIA_ID =" + n.getId() + " AND p.ID = np.listPiattaforme_ID ";
                l3 = em.createNativeQuery(strSQL2).getResultList();
                itr2 = l3.iterator();
                while (itr2.hasNext()) {
                    result2 = (Object[]) itr2.next();
                    p = new Piattaforma();
                    p.setId((Long) result2[0]);
                    p.setNome((String) result2[1]);
                    pl.add(p);
                }

                n.setListPiattaforme(pl);
                ris.add(n);
            }
        }
        return ris;


    }
    /**
     * Trova tutte le notizie presente nel Database che hanno nella loro lista di piattaforme un nome
     * che matcha con uno della lista dell parametro piattaforme nel Database
     * @param piattaforme lista dei nomi delle piattaforme da cercare tra tutte le piattaforme delle
     * notizie presente nel Database
     * @return Elenco di notizie, altrimenti restituisce una lista vuota
     */
    public List<Notizia> findPlatform(List<String> piattaforme) {
        List<Notizia> ris = null;
        //String strSQL ="select object(o) from Piattaforma as o where UPPER(o.nome) =\'\'" + piattaforma.toUpperCase() + "\'\'";   
        List l = new LinkedList() /*em.createQuery(strSQL).getResultList()*/;
        List<Piattaforma> pl = piattaformaFacade.estraiId(piattaforme);
        /*if (l.isEmpty())
         p=null;
         else{
         p=(Piattaforma)l.get(0);
         }*/
        ///////////////////////////////////////////////////////////////// 
        String strSQL2 = "SELECT n.ID, n.DATA, n.IMMAGINEPATH, n.TESTO, n.TITOLO, n.AUTORE_ID "
                + "FROM NOTIZIA n, NOTIZIA_PIATTAFORMA np, PIATTAFORMA p "
                + "WHERE  np.Notizia_ID = n.ID AND p.ID = np.listPiattaforme_ID ";
        // String strSQL = "select n from Notizia n LEFT JOIN FETCH n.listPiattaforme";funziona ma per restistuire tutti non si puo usare alias nella tabella NOTIZIA_PIATTAFORMA

        long idP;
        if (pl != null) {
            int i = 0;
            for (Piattaforma p : pl) {
                idP = p.getId();
                if (i == 0) {
                    strSQL2 += " AND (p.ID =" + idP;//oppure usare np.listPiattaforme_ID
                } else {
                    strSQL2 += " OR p.ID =" + idP;
                }
                i++;
            }
            strSQL2 = strSQL2 + ") order by n.data";
            List l2 = em.createNativeQuery(strSQL2).getResultList();//al posto di createQuery per l'uso di SQL puro standard
            List l3 = null;
            ris = new LinkedList<Notizia>();
            Iterator itr = l2.iterator();
            Iterator itr2 = null;

            Notizia n = null;
            // pl.add(p);
            Object[] result2 = null;
            Piattaforma p = null;
            while (itr.hasNext()) {
                pl = new LinkedList<Piattaforma>();
                Object[] result = (Object[]) itr.next();

                n = new Notizia();
                n.setId((Long) result[0]);
                n.setData((Date) result[1]);
                n.setImmaginePath((String) result[2]);
                n.setTesto((String) result[3]);
                n.setTitolo((String) result[4]);
                n.setAutore(utenteFacade.find(result[5]));

                /*              strSQL2 = "SELECT object(o) "
                 + "FROM NOTIZIA_PIATTAFORMA np, Piattaforma as o "
                 + "WHERE  np.Notizia_ID ="+n.getId()+" AND o.ID = np.listPiattaforme_ID";*/
                strSQL2 = "SELECT p.ID,p.NOME "
                        + "FROM NOTIZIA_PIATTAFORMA np, Piattaforma p "
                        + "WHERE  np.NOTIZIA_ID =" + n.getId() + " AND p.ID = np.listPiattaforme_ID";
                l3 = em.createNativeQuery(strSQL2).getResultList();
                itr2 = l3.iterator();
                while (itr2.hasNext()) {
                    result2 = (Object[]) itr2.next();
                    p = new Piattaforma();
                    p.setId((Long) result2[0]);
                    p.setNome((String) result2[1]);
                    pl.add(p);
                }

                n.setListPiattaforme(pl);
                ris.add(n);
            }

        }
        return ris;


    }
    
    @Override
    public List<Notizia> findAll(){
        
 String sql = "select n from Notizia n order by n.data";
            Query q = em.createQuery(sql);
    return q.getResultList();
    }
    
}
